home *** CD-ROM | disk | FTP | other *** search
-
- /*
- File: ShapeControlsLibrary.c
-
- Contains: graphics libraries - library to allow the user to manipulate (gxTransform) a set of shapes
-
- Written by: Dave Good and Jeff Kreegar
-
- Copyright: © 1995 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <2> 1/9/95 JD changed 'boolean' to 'Boolean'
- <1> 1/9/95 JD First checked in.
- */
-
- #include <Memory.h>
- #include <Events.h>
- #include <OSUtils.h>
- #include <ToolUtils.h>
- #include <GXErrors.h>
- #include <GXEnvironment.h>
- #include "GraphicsLibraries.h"
- #include "ShapeControlsLibrary.h"
-
-
- /*----------------------------------------------------------------------------------------------------*/
- /* private constants and structures */
- /*----------------------------------------------------------------------------------------------------*/
-
-
- /*** this is not used or completed; however it is a placeholder for the future */
- typedef struct portBuffer {
- gxViewGroup group;
- } portBuffer;
-
-
- typedef struct shapeControlRecord {
- /* ----- can be accessed in a public way ----- */
- gxShape items;
- gxShape foreground;
- gxShape background;
- gxShape selection;
- /* ----- private fields follow ----- */
- gxViewPort **originalPorts;
- gxShape controls;
- gxPoint savedCenter; /* this is either (gxPositiveInfinity, gxPositiveInfinity) or the saved rotate center */
- long buildHiddenLevel;
- gxRectangle **invalidAreas;
- } shapeControlRecord, *shapeControlPtr;
-
-
- #define controlHandleGap ff(6) /* this is the distance between the bounds of the gxShape and the bounds of the control handles */
- #define minimumObjectSizeH ff(2) /* this is the smallest horizontal size that an object may be scaled to */
- #define minimumObjectSizeV ff(2) /* this is the smallest vertical size that an object may be scaled to */
- #define rotateControlRadius ff(7)
- #define rotateCenterSize ff(2)
-
-
- typedef enum {
- /* ----- special commands ----- */
- firstSpecialCommand = -1,
- commandSelect = firstSpecialCommand,
- commandMove,
- lastSpecialCommand = commandMove,
- /* ----- indexes into the shapeControl->controls picture that correspond to different commands ----- */
- firstIndexCommand = 1,
- commandRotate = firstIndexCommand,
- commandMoveRotateCenter,
- commandScale,
- commandSkew = commandScale + 4,
- lastIndexCommand = commandSkew + 3,
- /* ----- modifiers for commandScale follow ----- */
- leftTop = 0,
- rightTop,
- rightBottom,
- leftBottom,
- /* ----- modifiers for commandSkew follow ----- */
- centerTop = 0,
- centerRight,
- centerBottom,
- centerLeft
- } shapeControlCommands;
-
-
- /*----------------------------------------------------------------------------------------------------*/
- /* private generic routines */
- /*----------------------------------------------------------------------------------------------------*/
-
-
- static Fixed FixedAbs(Fixed value)
- {
- if( value < 0 )
- return -value;
- return value;
- }
-
- static gxViewPort *DereferenceViewPortList(gxViewPort **list)
- {
- HLock((Handle)list);
- return *list;
- }
-
- static void ReleaseViewPortList(gxViewPort **list)
- {
- HUnlock((Handle)list);
- }
-
- static gxViewPort **NewViewPortListFromShape(gxShape source)
- {
- gxViewPort **list = (gxViewPort **)NewHandleClear((GXGetShapeViewPorts(source, nil) + 1) * sizeof(gxViewPort));
-
- IfErrorReturnNil(list == nil, out_of_memory);
- GXGetShapeViewPorts(source, DereferenceViewPortList(list));
- ReleaseViewPortList(list);
- return list;
- }
-
- static long CountViewPortList(gxViewPort **list)
- {
- return (GetHandleSize((Handle)list) / sizeof(gxViewPort)) - 1;
- }
-
- static void DisposeViewPortList(gxViewPort **list)
- {
- NilParamReturn(list);
- DisposeHandle((Handle)list);
- }
-
- static Boolean ShapeInPicture(gxShape test, gxShape picture)
- {
- long count;
-
- NilShapeReturnNil(test);
- NilShapeReturnNil(picture);
-
- count = GXGetPicture(picture, nil, nil, nil, nil);
- while( count ) {
- gxShape item;
-
- GXGetPictureParts(picture, count, 1, &item, nil, nil, nil);
- if( item == test )
- return true;
- --count;
- }
- return false;
- }
-
- static void GetPictureBounds(gxShape picture, gxRectangle *bounds, gxMapping *concatMatrix)
- {
- long count = GXGetPicture(picture, nil, nil, nil, nil);
-
- /* if there are no items in the picture, then there is nothing to do */
- if( count == 0 )
- return;
-
- do { gxShape item;
- gxTransform itemXform;
- gxMapping matrix;
-
- GXGetPictureParts(picture, count, 1, &item, nil, nil, &itemXform);
-
- /* if there was no overriding gxTransform, then use the item’s gxTransform. calculate the concatenated gxMapping */
- if( itemXform == nil )
- itemXform = GXGetShapeTransform(item);
- MapMapping(GXGetTransformMapping(itemXform, &matrix), concatMatrix);
-
- if( GXGetShapeType(item) == gxPictureType ) {
- GetPictureBounds(item, bounds, &matrix);
- } else {
- gxRectangle itemBounds;
- gxMapping tempMatrix;
- gxShape boundsShape = GXNewRectangle( GXGetShapeLocalBounds(item, &itemBounds) );
-
- /* map our bounds gxRectangle through the concatenated gxMapping. note that since GXGetShapeLocalBounds already
- maps the bounds by the item’s gxTransform, we need to undo this effect. */
- #ifdef debugging
- GXIgnoreGraphicsNotice(mapping_unaffected);
- #endif
- MapMapping(&matrix, InvertMapping(&tempMatrix, GXGetTransformMapping(GXGetShapeTransform(item), &tempMatrix)));
- GXMapShape(boundsShape, &matrix);
- #ifdef debugging
- GXPopGraphicsNotice();
- #endif
- /* get the bounds of our transformed bounds gxRectangle and then dispose of the temporary bounds gxShape */
- GXGetShapeBounds(boundsShape, 0L, &itemBounds);
- GXDisposeShape(boundsShape);
-
- /* union this item’s bounds into the main picture bounds (work around a problem with GXUnionRectangle) */
- if( bounds->right < bounds->left || bounds->bottom < bounds->top )
- *bounds = itemBounds;
- else
- GXUnionRectangle(bounds, bounds, &itemBounds);
- }
- } while( --count );
- }
-
- static gxRectangle *GetShapeTransformedBounds(gxShape source, gxRectangle *bounds)
- {
- gxMapping matrix;
-
- /* since graphics currently can’t get the correct bounds for a picture gxShape, we need special code */
- if( GXGetShapeType(source) == gxPictureType ) {
- bounds->left = bounds->top = gxPositiveInfinity;
- bounds->right = bounds->bottom = gxNegativeInfinity;
- GetPictureBounds( source, bounds, GXGetShapeMapping(source, &matrix) );
- return bounds;
- }
-
- /* otherwise, just use GXGetShapeLocalBounds */
- return GXGetShapeLocalBounds(source, bounds);
- }
-
- static gxPoint *GetShapeTransformedCenter(gxShape source, gxPoint *center)
- {
- gxMapping matrix;
-
- /* since graphics currently can’t calculate the center of picture shapes, we need special code */
- if( GXGetShapeType(source) == gxPictureType ) {
- gxRectangle bounds;
-
- GetShapeTransformedBounds(source, &bounds);
- center->x = (bounds.right >> 1) + (bounds.left >> 1);
- center->y = (bounds.top >> 1) + (bounds.bottom >> 1);
- } else
- MapPoints( GXGetShapeMapping(source, &matrix), 1, GXGetShapeCenter(source, 0L, center) );
- return center;
- }
-
-
- /*----------------------------------------------------------------------------------------------------*/
- /* private internal routines */
- /*----------------------------------------------------------------------------------------------------*/
-
-
- #if 0
- static Boolean AllocateOffscreen(shapeControl source)
- {
- return false;
- gxBitmap deepestBits;
- gxShape area;
-
- /* this ensures that the first device that we find will be put in deepestBits */
- deepestBits.pixelSize = -1;
-
- area = GXNewShape(gxFullType);
- GXSetShapeViewPorts(area, portCount, ports);
- while( portCount-- ) {
- gxViewDevice devices[maximumViewThings];
- long deviceCount;
-
- if( (deviceCount = GXGetShapeGlobalViewDevices(area, ports[portCount], devices)) > maximumViewThings )
- DebugStr("\pexceded the maximum number of viewDevices for a gxShape control");
- while( deviceCount-- ) {
- gxShape bitsShape;
- gxBitmap bits;
-
- bitsShape = GXGetViewDeviceBitmap(devices[deviceCount]);
- GXGetBitmap(bitsShape, &bits, nil);
- if( bits.pixelSize > deepestBits.pixelSize )
- deepestBits = bits;
- GXDisposeShape(bitsShape);
- }
- }
- GXDisposeShape(area);
-
- if( deepestBits.pixelSize > 0 ) {
- gxShape bitsShape;
-
- deepestBits.image = nil; /* make graphics allocate our offscreen bit image */
- bitsShape = GXNewBitmap(&deepestBits, nil);
- CreateOffscreen(&source->buffer, bitsShape);
- GXDisposeShape(bitsShape);
- } else
- FillBytes(&source->buffer, sizeof(source->buffer), 0);
-
- /*** needs work */
- }
- #endif
-
- static void InvalidateRectangle(shapeControlPtr targetPtr, gxRectangle *newArea)
- {
- if( targetPtr->invalidAreas ) {
- gxRectangle *listPtr = *targetPtr->invalidAreas;
- gxRectangle *maxPtr = (gxRectangle *)((char *)listPtr + GetHandleSize((Handle)targetPtr->invalidAreas));
-
- while( listPtr != maxPtr &&
- (listPtr->top < newArea->top || listPtr->top == newArea->top && listPtr->left < newArea->left) ) {
- ++listPtr;
- }
- Munger((Handle)targetPtr->invalidAreas, (char *)listPtr - (char *)*targetPtr->invalidAreas, nil, 0,
- (Ptr)newArea, sizeof(gxRectangle));
- } else {
- targetPtr->invalidAreas = (gxRectangle **)NewHandle(sizeof(gxRectangle));
- **targetPtr->invalidAreas = *newArea;
-
- /*** reduce the gxRectangle list here */
- }
-
- #if 0 /* re-enable this to show which areas will be updated */
- { gxShape invalidShape = GXNewRectangle(newArea);
- #ifdef debugging
- GXIgnoreGraphicsNotice(color_already_set);
- #endif
- SetShapeCommonColor(invalidShape, gxBlack);
- #ifdef debugging
- GXPopGraphicsNotice();
- #endif
- GXDrawShape(invalidShape);
- GXDisposeShape(invalidShape);
- }
- #endif
- }
-
- static void InvalidatePicture(shapeControlPtr targetPtr, gxShape control)
- {
- /*** later, we need to fix the picture code below and then only invalidate the bounds of the sub-items */
- if( false && GXGetShapeType(control) == gxPictureType ) {
- long count = GXGetPicture(control, nil, nil, nil, nil);
- while( count > 0 ) {
- gxShape item;
- gxTransform itemXform, originalXform;
- gxRectangle bounds;
-
- GXGetPictureParts(control, count, 1, &item, nil, nil, &itemXform);
- if( itemXform ) {
- originalXform = GXGetShapeTransform(item);
- GXSetShapeTransform(item, itemXform);
- }
- InvalidateRectangle(targetPtr, GetShapeTransformedBounds(item, &bounds));
- if( itemXform )
- GXSetShapeTransform(item, originalXform);
- --count;
- }
- } else {
- gxRectangle bounds;
- InvalidateRectangle(targetPtr, GetShapeTransformedBounds(control, &bounds));
- }
- }
-
- static void RedrawShapeControl(shapeControlPtr targetPtr)
- {
- if( targetPtr->invalidAreas ) {
- gxRectangle *listPtr, *maxPtr;
-
- /* lock down our handle of rectangular invalid areas */
- HLock((Handle)targetPtr->invalidAreas);
- listPtr = *targetPtr->invalidAreas;
- maxPtr = (gxRectangle *)((char *)listPtr + GetHandleSize((Handle)targetPtr->invalidAreas));
-
- do { gxShape clip;
- gxViewPort *portList, *childList;
- gxViewPort **childPorts;
-
- /* make a gxViewPort list for all of our child ports (these will hold our invalid clip) */
- childPorts = (gxViewPort **)NewHandleClear( GetHandleSize((Handle)targetPtr->originalPorts) );
- childList = DereferenceViewPortList(childPorts);
-
- /* clip all of the viewPorts that we are drawing into to our current invalid gxRectangle */
- clip = GXNewRectangle(listPtr);
- portList = DereferenceViewPortList(targetPtr->originalPorts);
- while( *portList ) {
- *childList = GXNewViewPort(GXGetViewPortViewGroup(*portList));
- GXSetViewPortParent(*childList, *portList);
- GXSetViewPortClip(*childList, clip);
- ++portList;
- ++childList;
- }
- ReleaseViewPortList(targetPtr->originalPorts);
- GXDisposeShape(clip);
-
- /* re-direct all of our drawing into the child viewPorts */
- #ifdef debugging
- GXIgnoreGraphicsNotice(transform_viewPorts_already_set);
- #endif
- { long portCount = CountViewPortList(childPorts);
-
- childList = *childPorts;
- GXSetShapeViewPorts(targetPtr->background, portCount, childList);
- if( targetPtr->foreground )
- GXSetShapeViewPorts(targetPtr->foreground, portCount, childList);
- if( targetPtr->controls )
- GXSetShapeViewPorts(targetPtr->controls, portCount, childList);
- }
- #ifdef debugging
- GXPopGraphicsNotice();
- #endif
-
- GXDrawShape(targetPtr->background);
-
- /* draw all the items in the picture, one at a time in the proper order using our clip */
- #if 1
- { long count = GXGetPicture(targetPtr->items, nil, nil, nil, nil);
- long index;
-
- for(index = 1; index <= count; ++index ) {
- gxViewPort **itemList;
- gxShape item;
-
- GXGetPictureParts(targetPtr->items, index, 1, &item, nil, nil, nil);
-
- /* save the item’s gxViewPort list and re-direct the item into our childPorts */
- itemList = NewViewPortListFromShape(item);
- GXSetShapeViewPorts(item, CountViewPortList(childPorts), *childPorts);
-
- GXDrawShape(item);
-
- /* restore the item’s gxViewPort list and throw away our saved list memory */
- DereferenceViewPortList(itemList);
- GXSetShapeViewPorts(item, CountViewPortList(itemList), *itemList);
- DisposeViewPortList(itemList);
- }
- }
- #else
- GXDrawShape(targetPtr->items);
- #endif
-
- if( targetPtr->foreground )
- GXDrawShape(targetPtr->foreground);
- if( targetPtr->controls )
- GXDrawShape(targetPtr->controls);
-
- /* re-direct all of our drawing back into the main viewPorts */
- #ifdef debugging
- GXIgnoreGraphicsNotice(transform_viewPorts_already_set);
- #endif
- {
- long portCount = CountViewPortList(targetPtr->originalPorts);
-
- portList = DereferenceViewPortList(targetPtr->originalPorts);
- GXSetShapeViewPorts(targetPtr->background, portCount, portList);
- if( targetPtr->foreground )
- GXSetShapeViewPorts(targetPtr->foreground, portCount, portList);
- if( targetPtr->controls )
- GXSetShapeViewPorts(targetPtr->controls, portCount, portList);
- ReleaseViewPortList(targetPtr->originalPorts);
- }
- #ifdef debugging
- GXPopGraphicsNotice();
- #endif
- /* dispose of all the viewPorts in the child list and then dispose of the child list itself */
- childList = DereferenceViewPortList(childPorts);
- while( *childList )
- GXDisposeViewPort(*childList++);
- ReleaseViewPortList(childPorts);
- DisposeViewPortList(childPorts);
- } while( ++listPtr < maxPtr );
-
- /* throw away all the invalid areas since we have just updated them */
- DisposeHandle((Handle)targetPtr->invalidAreas);
- targetPtr->invalidAreas = nil;
- }
- }
-
- static void BuildSelectionControls(shapeControlPtr targetPtr)
- {
- gxRectangle bounds, controlBounds;
- gxShape controls, workShape;
-
- /* don’t re-build anything if building is hidden */
- if( targetPtr->buildHiddenLevel )
- return;
-
- /* throw away the old controls and see if there is a selection; if not, then we are done */
- DisposeShapeAt(&targetPtr->controls);
- if( targetPtr->selection == nil )
- return;
-
- /* create a new controls picture in all of our viewPorts */
- controls = targetPtr->controls = GXNewShape(gxPictureType);
- { gxViewPort *portList = DereferenceViewPortList(targetPtr->originalPorts);
- GXSetShapeViewPorts(targetPtr->controls, CountViewPortList(targetPtr->originalPorts), portList);
- ReleaseViewPortList(targetPtr->originalPorts); }
-
- /* get the bounds of the entire selection and calculate the controlBounds */
- GetShapeTransformedBounds(targetPtr->selection, &bounds);
- IfDebug(bounds.right < bounds.left || bounds.bottom < bounds.top, "\pthe selection should always have a bounds here");
- controlBounds.left = bounds.left - controlHandleGap;
- controlBounds.top = bounds.top - controlHandleGap;
- controlBounds.right = bounds.right + controlHandleGap;
- controlBounds.bottom = bounds.bottom + controlHandleGap;
-
- /* create the scale controls (these are simply rotated images of each other) */
- { static long scalePoly[] = { 1, 4,
- ff(0), ff(0),
- ff(5) + 0x5000, ff(0),
- ff(0), ff(5) + 0x5000,
- ff(0), ff(0)
- };
- gxShape tempShape;
-
- workShape = GXNewPolygons((gxPolygons *)scalePoly);
- GXSetShapeFill(workShape, gxWindingFill);
- #ifdef debugging
- GXIgnoreGraphicsNotice(color_already_set);
- #endif
- SetShapeCommonColor(workShape, gxBlack);
- #ifdef debugging
- GXPopGraphicsNotice();
- #endif
- tempShape = GXCopyToShape(nil, workShape);
- GXMoveShapeTo(tempShape, controlBounds.left, controlBounds.top);
- GXSetPictureParts(controls, 0, 0, 1, &tempShape, nil, nil, nil);
- GXDisposeShape(tempShape);
-
- GXRotateShape(workShape, ff(90), ff(0), ff(0));
- tempShape = GXCopyToShape(nil, workShape);
- GXMoveShapeTo(tempShape, controlBounds.right, controlBounds.top);
- GXSetPictureParts(controls, 0, 0, 1, &tempShape, nil, nil, nil);
- GXDisposeShape(tempShape);
-
- GXRotateShape(workShape, ff(90), ff(0), ff(0));
- tempShape = GXCopyToShape(nil, workShape);
- GXMoveShapeTo(tempShape, controlBounds.right, controlBounds.bottom);
- GXSetPictureParts(controls, 0, 0, 1, &tempShape, nil, nil, nil);
- GXDisposeShape(tempShape);
-
- GXRotateShape(workShape, ff(90), ff(0), ff(0));
- tempShape = GXCopyToShape(nil, workShape);
- GXMoveShapeTo(tempShape, controlBounds.left, controlBounds.bottom);
- GXSetPictureParts(controls, 0, 0, 1, &tempShape, nil, nil, nil);
- GXDisposeShape(tempShape);
-
- GXDisposeShape(workShape);
- }
-
- /* create the skew controls in (top, right, bottom, left) order */
- { static long skewPoly[] = { 1, 5,
- -ff(3), ff(0),
- ff(0), -ff(3),
- ff(3), ff(0),
- ff(0), ff(3),
- -ff(3), ff(0)
- };
- gxShape tempShape;
- gxPoint center;
-
- center.x = (bounds.right >> 1) + (bounds.left >> 1);
- center.y = (bounds.top >> 1) + (bounds.bottom >> 1);
-
- workShape = GXNewPolygons((gxPolygons *)skewPoly);
- GXSetShapeFill(workShape, gxWindingFill);
- #ifdef debugging
- GXIgnoreGraphicsNotice(color_already_set);
- #endif
- SetShapeCommonColor(workShape, gxBlack);
- #ifdef debugging
- GXPopGraphicsNotice();
- #endif
-
- tempShape = GXCopyToShape(nil, workShape);
- GXMoveShape(tempShape, center.x, controlBounds.top);
- GXSetPictureParts(controls, 0, 0, 1, &tempShape, nil, nil, nil);
- GXDisposeShape(tempShape);
-
- tempShape = GXCopyToShape(nil, workShape);
- GXMoveShape(tempShape, controlBounds.right + ff(1), center.y);
- GXSetPictureParts(controls, 0, 0, 1, &tempShape, nil, nil, nil);
- GXDisposeShape(tempShape);
-
- tempShape = GXCopyToShape(nil, workShape);
- GXMoveShape(tempShape, center.x, controlBounds.bottom + ff(3));
- GXSetPictureParts(controls, 0, 0, 1, &tempShape, nil, nil, nil);
- GXDisposeShape(tempShape);
-
- tempShape = GXCopyToShape(nil, workShape);
- GXMoveShape(tempShape, controlBounds.left, center.y);
- GXSetPictureParts(controls, 0, 0, 1, &tempShape, nil, nil, nil);
- GXDisposeShape(tempShape);
-
- GXDisposeShape(workShape);
- }
-
- /* create the rotate control and its center gxPoint */
- { gxRectangle tempRect;
- gxPoint center;
-
- /* get the center of the selection (or the individual gxShape) for the rotate control and its center gxPoint */
- if( targetPtr->savedCenter.x != gxPositiveInfinity ) {
- center = targetPtr->savedCenter;
- } else if( GXGetPicture(targetPtr->selection, nil, nil, nil, nil) == 1 ) {
- gxShape item;
-
- GXGetPicture(targetPtr->selection, &item, nil, nil, nil);
- GetShapeTransformedCenter(item, ¢er);
- } else {
- center.x = (bounds.right >> 1) + (bounds.left >> 1);
- center.y = (bounds.top >> 1) + (bounds.bottom >> 1);
- }
-
- /* create the rotate control */
- tempRect.left = center.x - rotateControlRadius;
- tempRect.top = center.y - rotateControlRadius;
- tempRect.right = center.x + rotateControlRadius;
- tempRect.bottom = center.y + rotateControlRadius;
- workShape = NewOval(&tempRect);
- GXSetShapeFill(workShape, gxClosedFrameFill);
- #ifdef debugging
- GXIgnoreGraphicsNotice(color_already_set);
- #endif
- SetShapeCommonColor(workShape, gxBlack);
- #ifdef debugging
- GXPopGraphicsNotice();
- #endif
- #if useFilledOval
- GXSetShapePen(workShape, ff(2));
- GXPrimitiveShape(workShape);
- GXSetShapeFill(workShape, gxWindingFill);
- #endif
- GXSetPictureParts(controls, 1, 0, 1, &workShape, nil, nil, nil);
- GXDisposeShape(workShape);
-
- /* create the rotate center */
- tempRect.left = center.x - rotateCenterSize;
- tempRect.top = center.y - rotateCenterSize;
- tempRect.right = center.x + rotateCenterSize;
- tempRect.bottom = center.y + rotateCenterSize;
- workShape = NewOval(&tempRect);
- GXSetShapeFill(workShape, gxWindingFill);
- #ifdef debugging
- GXIgnoreGraphicsNotice(color_already_set);
- #endif
- SetShapeCommonColor(workShape, gxBlack);
- #ifdef debugging
- GXPopGraphicsNotice();
- #endif
- GXSetPictureParts(controls, 2, 0, 1, &workShape, nil, nil, nil);
- GXDisposeShape(workShape);
- }
-
- /* reset the savedCenter to the “no center saved” value */
- targetPtr->savedCenter.x = targetPtr->savedCenter.y = gxPositiveInfinity;
- }
-
- static void TrackShapeControl(shapeControlPtr targetPtr, long command, gxPoint originalClick)
- {
- Boolean hiddenControls = false;
- Boolean rebuildControls = false;
- gxPolar originalPolar;
- gxPoint originalSize;
- gxPoint pivot;
- gxPoint adjust;
- gxMapping oldMatrix;
- gxPoint oldMouse = originalClick;
- Fixed polySrc[10];
- Fixed polyDst[10];
-
- /* if we are rotating, then calculate the pivot gxPoint for the rotation and save the original angle */
- if( command == commandRotate ) {
- gxShape centerShape;
- gxPoint tempPoint;
-
- GXGetPictureParts(targetPtr->controls, commandMoveRotateCenter, 1, ¢erShape, nil, nil, nil);
- GetShapeTransformedCenter(centerShape, &pivot);
- tempPoint.x = originalClick.x - pivot.x;
- tempPoint.y = originalClick.y - pivot.y;
- PointToPolar(&tempPoint, &originalPolar);
- targetPtr->savedCenter = pivot;
- } else if( command >= commandScale && command <= commandSkew + 3 ) {
- gxRectangle bounds;
-
- /* get the bounds of the entire selection for all the commands that require it */
- GetShapeTransformedBounds(targetPtr->selection, &bounds);
- IfDebug(bounds.right < bounds.left || bounds.bottom < bounds.top, "\pthe selection should always have a bounds here");
-
- /* calculate the originalSize of the selection and set the original scale gxMapping to identity */
- originalSize.x = bounds.right - bounds.left;
- originalSize.y = bounds.bottom - bounds.top;
- ResetMapping(&oldMatrix);
-
- /* calculate the pivot (or anchor) gxPoint for the scale */
- switch( command ) {
- case commandScale + leftTop:
- pivot.x = bounds.right;
- pivot.y = bounds.bottom;
- break;
- case commandScale + rightTop:
- pivot.x = bounds.left;
- pivot.y = bounds.bottom;
- break;
- case commandScale + rightBottom:
- pivot.x = bounds.left;
- pivot.y = bounds.top;
- break;
- case commandScale + leftBottom:
- pivot.x = bounds.right;
- pivot.y = bounds.top;
- break;
- default:
- polySrc[0] = 4;
- polySrc[1] = bounds.left;
- polySrc[2] = bounds.top;
- polySrc[3] = bounds.right;
- polySrc[4] = bounds.top;
- polySrc[5] = bounds.right;
- polySrc[6] = bounds.bottom;
- polySrc[7] = bounds.left;
- polySrc[8] = bounds.bottom;
- BlockMove(&polySrc[0], &polyDst[0], sizeof(polySrc));
- }
-
- /* this is the amount that we must adjust the mouse position by in order to have the scaling come out correct */
- adjust.x = FixedAbs(originalClick.x - pivot.x) - originalSize.x;
- adjust.y = FixedAbs(originalClick.y - pivot.y) - originalSize.y;
- }
-
- while( StillDown() ) {
- gxPoint newMouse;
-
- GXGetViewPortMouse(0, &newMouse);
- if( newMouse.x != oldMouse.x || newMouse.y != oldMouse.y ) {
- Fixed deltaX = newMouse.x - oldMouse.x;
- Fixed deltaY = newMouse.y - oldMouse.y;
- gxMapping newMatrix;
- gxRectangle bounds;
- long count;
- gxShape item;
-
- /* if the controls are not hidden yet, then do so now, unless we are moving the rotate center */
- if( command != commandMoveRotateCenter && ! hiddenControls ) {
- /* set our flag so that we won’t try to hide the controls again */
- hiddenControls = true;
-
- /* mark the area covered by the controls as invalid and then temporarily hide the controls picture */
- InvalidatePicture(targetPtr, targetPtr->controls);
- GXSetShapeFill(targetPtr->controls, gxNoFill);
- RedrawShapeControl(targetPtr);
- }
-
- switch( command ) {
-
- case commandSelect:
- /*** needs work */
- break;
-
- case commandMove:
- /* move all the items in the selection, marking their old and new bounds as redraw areas */
- count = GXGetPicture(targetPtr->selection, nil, nil, nil, nil);
- IfDebug(count == 0, "\pthe selection should always have items in it here");
- do {
- GXGetPictureParts(targetPtr->selection, count, 1, &item, nil, nil, nil);
- InvalidateRectangle(targetPtr, GetShapeTransformedBounds(item, &bounds));
- GXMoveShape(item, deltaX, deltaY);
- InvalidateRectangle(targetPtr, GetShapeTransformedBounds(item, &bounds));
- } while( --count );
-
- /* move the controls for all the selected items and update the screen to reflect the new position */
- GXMoveShape(targetPtr->controls, deltaX, deltaY);
- RedrawShapeControl(targetPtr);
- break;
-
- case commandRotate:
- { gxPoint tempPoint;
- gxPolar newPolar;
-
- tempPoint.x = newMouse.x - pivot.x;
- tempPoint.y = newMouse.y - pivot.y;
- PointToPolar(&tempPoint, &newPolar);
-
- /* rotate all the items in the selection, marking their old and new bounds as redraw areas */
- count = GXGetPicture(targetPtr->selection, nil, nil, nil, nil);
- IfDebug(count == 0, "\pthe selection should always have items in it here");
- do {
- GXGetPictureParts(targetPtr->selection, count, 1, &item, nil, nil, nil);
- InvalidateRectangle(targetPtr, GetShapeTransformedBounds(item, &bounds));
- GXRotateShape(item, newPolar.angle - originalPolar.angle, pivot.x, pivot.y);
- InvalidateRectangle(targetPtr, GetShapeTransformedBounds(item, &bounds));
- } while( --count );
-
- /* copy the newPolar into the originalPolar for our next pass through the loop */
- originalPolar = newPolar;
-
- /* invalidate the controls for all the selected items and update the screen to reflect the new position */
- rebuildControls = true;
- RedrawShapeControl(targetPtr);
- break;
- }
-
- case commandMoveRotateCenter:
- { long index;
-
- /* move the rotate center control part and the rotate control part */
- for(index = commandRotate; index <= commandMoveRotateCenter; ++index) {
- gxShape control;
- gxTransform xform;
- long pass;
-
- GXGetPictureParts(targetPtr->controls, index, 1, &control, nil, nil, &xform);
- /* invalidate the position before the move and the position after the move */
- for( pass = 0; pass <= 1; ++pass ) {
- gxShape boundsShape;
- gxTransform originalXform;
- gxMapping matrix;
-
- if( xform ) {
- originalXform = GXGetShapeTransform(control);
- GXSetShapeTransform(control, xform);
- }
- boundsShape = GXNewRectangle(GetShapeTransformedBounds(control, &bounds));
- if( xform )
- GXSetShapeTransform(control, originalXform);
- GXMapShape(boundsShape, GXGetShapeMapping(targetPtr->controls, &matrix));
- GXGetShapeBounds(boundsShape, 0L, &bounds);
- GXDisposeShape(boundsShape);
- InvalidateRectangle(targetPtr, &bounds);
-
- /* if we are on our first pass, then move the control */
- if( pass == 0 )
- GXMoveShape(control, deltaX, deltaY);
- }
- }
-
- /* update the screen to reflect the new positions of these controls */
- RedrawShapeControl(targetPtr);
- break;
- }
-
- /* scale the gxShape around the pivot gxPoint */
- case commandScale + leftTop:
- case commandScale + rightTop:
- case commandScale + rightBottom:
- case commandScale + leftBottom:
- { Fixed scaleX, scaleY;
-
- /* calculate the scale values for the selection */
- scaleX = FixedDivide(FixedAbs(newMouse.x - pivot.x) - adjust.x, originalSize.x);
- scaleY = FixedDivide(FixedAbs(newMouse.y - pivot.y) - adjust.y, originalSize.y);
-
- /* if we are on the other side of the pivot gxPoint from where we started, then negate the scale */
- if( ((newMouse.x - pivot.x) ^ (originalClick.x - pivot.x)) < 0 )
- scaleX = -scaleX;
- if( ((newMouse.y - pivot.y) ^ (originalClick.y - pivot.y)) < 0 )
- scaleY = -scaleY;
-
- /* save our new true scale gxMapping and calculate the delta gxMapping to apply to all the shapes */
- ResetMapping(&newMatrix);
- ScaleMapping(&newMatrix, scaleX, scaleY, pivot.x, pivot.y);
- goto mapSelection;
- }
-
- case commandSkew + centerTop:
- polyDst[1] += deltaX;
- polyDst[2] += deltaY;
- polyDst[3] = polyDst[1] + originalSize.x;
- polyDst[4] = polyDst[2];
- goto skewSelection;
-
- case commandSkew + centerRight:
- polyDst[3] += deltaX;
- polyDst[4] += deltaY;
- polyDst[5] = polyDst[3];
- polyDst[6] = polyDst[4] + originalSize.y;
- goto skewSelection;
-
- case commandSkew + centerBottom:
- polyDst[7] += deltaX;
- polyDst[8] += deltaY;
- polyDst[5] = polyDst[7] + originalSize.x;
- polyDst[6] = polyDst[8];
- goto skewSelection;
-
- case commandSkew + centerLeft:
- polyDst[1] += deltaX;
- polyDst[2] += deltaY;
- polyDst[7] = polyDst[1];
- polyDst[8] = polyDst[2] + originalSize.y;
- /* fall through into “skewSelection” */
-
- skewSelection: PolyToPolyMap((gxPolygon *)&polySrc, (gxPolygon *)&polyDst, &newMatrix);
- /* fall through into “mapSelection” */
-
- mapSelection: { gxMapping deltaMatrix, tempMatrix;
-
- /* calculate the delta gxMapping */
- CopyToMapping(&tempMatrix, &newMatrix);
- InvertMapping(&deltaMatrix, &oldMatrix);
- MapMapping(&deltaMatrix, &tempMatrix);
-
- /* map all the shapes in the selection (and invalidate them) */
- count = GXGetPicture(targetPtr->selection, nil, nil, nil, nil);
- IfDebug(count == 0, "\pthe selection should always have items in it here");
- do { gxShape itemCopy;
-
- GXGetPictureParts(targetPtr->selection, count, 1, &item, nil, nil, nil);
- itemCopy = GXCopyToShape(nil, item);
- GXMapShape(itemCopy, &deltaMatrix);
- GetShapeTransformedBounds(itemCopy, &bounds);
- GXDisposeShape(itemCopy);
- if( bounds.right >= bounds.left + minimumObjectSizeH &&
- bounds.bottom >= bounds.top + minimumObjectSizeV ) {
- InvalidateRectangle(targetPtr, GetShapeTransformedBounds(item, &bounds));
- GXMapShape(item, &deltaMatrix);
- InvalidateRectangle(targetPtr, GetShapeTransformedBounds(item, &bounds));
- } else {
- /* if the object would have disappeared, then keep the objects old full-delta gxMapping */
- CopyToMapping(&newMatrix, &oldMatrix);
- }
- } while( --count );
-
- /* save the new full-delta gxMapping in our original gxMapping variable */
- CopyToMapping(&oldMatrix, &newMatrix);
-
- /* update the screen to reflect changes to the gxShape and invalidate the controls */
- RedrawShapeControl(targetPtr);
- rebuildControls = true;
- break;
- }
- }
-
- oldMouse = newMouse;
- }
- }
-
- /* if we changed the geometry of the selection, then re-build the controls for it */
- if( rebuildControls )
- BuildSelectionControls(targetPtr);
-
- if( hiddenControls ) {
- GXSetShapeFill(targetPtr->controls, gxEvenOddFill);
- GXDrawShape(targetPtr->controls);
- }
- }
-
- static void DeselectShape(shapeControlPtr targetPtr, gxShape item)
- {
- if( targetPtr->selection ) {
- long count = GXGetPicture(targetPtr->selection, nil, nil, nil, nil);
- gxShape temp;
-
- do {
- GXGetPictureParts(targetPtr->selection, count, 1, &temp, nil, nil, nil);
- } while( temp != item && --count );
-
- /* if we actually found the item in the selection, then de-select it */
- if( count ) {
- /* invalidate the controls for the selection, since we are changing it */
- InvalidatePicture(targetPtr, targetPtr->controls);
-
- /* remove the item from the selection picture and dispose of the picture item was the only selected gxShape */
- GXSetPictureParts(targetPtr->selection, count, 1, 0, nil, nil, nil, nil);
- if( GXGetPicture(targetPtr->selection, nil, nil, nil, nil) == 0 )
- DisposeShapeAt(&targetPtr->selection);
-
- /* rebuild the controls for the selection */
- BuildSelectionControls(targetPtr);
- }
- }
- }
-
- static void SelectShape(shapeControlPtr targetPtr, gxShape item, Boolean replaceSelection, Boolean bringToFront)
- {
- /* move the passed item gxShape to the front of the picture if we are supposed to do so */
- if( bringToFront ) {
- long index = GXGetPicture(targetPtr->items, nil, nil, nil, nil);
- gxShape tempShape;
-
- IfDebug(index == 0, "\ptargetPtr->items must always have items");
- do {
- GXGetPictureParts(targetPtr->items, index, 1, &tempShape, nil, nil, nil);
- if( tempShape == item ) {
- gxRectangle bounds;
-
- /* add the gxShape to the end first, then remove it so that our references are always valid */
- GXSetPictureParts(targetPtr->items, 0, 0, 1, &item, nil, nil, nil);
- GXSetPictureParts(targetPtr->items, index, 1, 0, nil, nil, nil, nil);
- InvalidateRectangle(targetPtr, GetShapeTransformedBounds(item, &bounds));
- }
- } while( --index );
- }
-
- /* if we are replacing the selection, then un-select all the selected shapes */
- if( replaceSelection && targetPtr->selection ) {
- InvalidatePicture(targetPtr, targetPtr->controls);
- DisposeShapeAt(&targetPtr->selection);
- DisposeShapeAt(&targetPtr->controls);
- }
-
- /* if there is an old selection that we are adding to, then invalidate the area for its controls */
- if( targetPtr->controls )
- InvalidatePicture(targetPtr, targetPtr->controls);
-
- if( item == nil ) {
- DisposeShapeAt(&targetPtr->controls);
- return;
- }
-
- if( targetPtr->selection == nil ) {
- targetPtr->selection = GXNewPicture(1, &item, nil, nil, nil);
- } else {
- long count = GXGetPicture(targetPtr->selection, nil, nil, nil, nil);
- long index = 0;
- gxShape selectionItem;
- gxShape mainItem;
-
- /* look through the selection for the first gxShape AFTER item in the main items picture; insert item before this index */
- IfDebug(count == 0, "\pselection must have items in it here");
- do { long mainIndex = 0;
-
- GXGetPictureParts(targetPtr->selection, ++index, 1, &selectionItem, nil, nil, nil);
- do {
- IfDebug(mainIndex == GXGetPicture(targetPtr->items, nil, nil, nil, nil),
- "\pselected item not in main items picture");
- GXGetPictureParts(targetPtr->items, ++mainIndex, 1, &mainItem, nil, nil, nil);
- } while( mainItem != selectionItem && mainItem != item );
- } while( mainItem == selectionItem && --count );
-
- /* if we hit the end of the selection without finding a gxShape after item, then set index to zero to insert at the end */
- if( count == 0 ) index = 0;
-
- /* insert our newly selected item in the correct place in the selection */
- GXSetPictureParts(targetPtr->selection, index, 0, 1, &item, nil, nil, nil);
- }
-
- /* calculate the geometry of the controls for the selection and invalidate this new area */
- BuildSelectionControls(targetPtr);
- InvalidatePicture(targetPtr, targetPtr->controls);
- }
-
-
- /*----------------------------------------------------------------------------------------------------*/
- /* public routines */
- /*----------------------------------------------------------------------------------------------------*/
-
-
- shapeControl NewShapeControl(gxShape items, gxShape background, gxShape foreground)
- {
- shapeControl target;
-
- NilShapeReturnNil(items);
- IfWarningReturnNil(GXGetShapeType(items) != gxPictureType, picture_expected);
- IfDebug(firstIndexCommand <= lastSpecialCommand, "\pinvalid gxShape control commands - bug in gxShape control library");
-
- if( (target = (shapeControl)NewHandleClear(sizeof(shapeControlRecord))) != 0 ) {
- gxViewPort **originalPorts = NewViewPortListFromShape(items);
- shapeControlPtr targetPtr;
-
- HLock((Handle)target);
- targetPtr = *target;
-
- targetPtr->items = GXCloneShape(items);
-
- if( background )
- targetPtr->background = GXCloneShape(background);
- else {
- gxColor whiteColor;
-
- /* if there is no background, then create a white full gxShape (we always need some sort of background) */
- targetPtr->background = GXNewShape(gxFullType);
- whiteColor.space = gxRGBSpace;
- whiteColor.profile = nil;
- whiteColor.element.rgb.red = 0xFFFF;
- whiteColor.element.rgb.green = 0xFFFF;
- whiteColor.element.rgb.blue = 0xFFFF;
- GXSetShapeColor(targetPtr->background, &whiteColor);
- }
- /* ensure that the background draws to the same ports as the items */
- DereferenceViewPortList(originalPorts);
- #ifdef debugging
- GXIgnoreGraphicsNotice(transform_viewPorts_already_set);
- #endif
- GXSetShapeViewPorts(targetPtr->background, CountViewPortList(originalPorts), *originalPorts);
- #ifdef debugging
- GXPopGraphicsNotice();
- #endif
- if( foreground ) {
- targetPtr->foreground = GXCloneShape(foreground);
- GXSetShapeViewPorts(targetPtr->foreground, CountViewPortList(originalPorts), *originalPorts);
- }
-
- /* set the savedCenter to the “no center saved” value */
- targetPtr->savedCenter.x = targetPtr->savedCenter.y = gxPositiveInfinity;
-
- ReleaseViewPortList(originalPorts);
- targetPtr->originalPorts = originalPorts;
- HUnlock((Handle)target);
- }
-
- return target;
- }
-
-
- void DisposeShapeControl(shapeControl target)
- {
- shapeControlPtr targetPtr;
-
- NilParamReturn(target);
-
- HLock((Handle)target);
- targetPtr = *target;
- GXDisposeShape(targetPtr->items);
- GXDisposeShape(targetPtr->background);
- DisposeShapeAt(&targetPtr->foreground);
- DisposeShapeAt(&targetPtr->selection);
- DisposeShapeAt(&targetPtr->controls);
- DisposeViewPortList(targetPtr->originalPorts);
- HUnlock((Handle)target);
-
- /* dispose of the gxShape control memory itself */
- DisposeHandle((Handle)target);
- }
-
-
- gxShape GetShapeControlSelection(const shapeControl source)
- {
- NilParamReturn(source);
-
- if( (*source)->selection )
- return GXCopyToShape(nil, (*source)->selection);
- else
- return nil;
- }
-
-
- void SetShapeControlsSelection(shapeControl target, gxShape shapesToSelect, Boolean bringToFront, Boolean replaceSelection)
- {
- shapeControlPtr targetPtr;
- long count;
- Boolean updateControls = false;
-
- NilParamReturn(target);
- HLock((Handle)target);
- targetPtr = *target;
-
- /* prevent the selection’s controls from getting re-build by the various intermediate steps */
- ++targetPtr->buildHiddenLevel;
-
- /* if we are replacing the old selection, then de-select all the old shapes that will not be in the new selection */
- if( replaceSelection && targetPtr->selection ) {
- count = GXGetPicture(targetPtr->selection, nil, nil, nil, nil);
-
- do { /* scan through all the items in the selection, de-selecting all the ones not in shapesToSelect */
- gxShape item;
- Boolean itemInNewSelection;
-
- GXGetPictureParts(targetPtr->selection, count, 1, &item, nil, nil, nil);
- itemInNewSelection = false;
- if( shapesToSelect == nil || (shapesToSelect != item && GXGetShapeType(shapesToSelect) == gxPictureType
- && ShapeInPicture(item, shapesToSelect) == false) ) {
- updateControls = true;
- GXSetPictureParts(targetPtr->selection, count, 1, 0, nil, nil, nil, nil);
- }
- } while( --count );
-
- if( GXGetPicture(targetPtr->selection, nil, nil, nil, nil) == 0 ) {
- DisposeShapeAt(&targetPtr->selection);
- DisposeShapeAt(&targetPtr->controls);
- }
- }
-
- /* if there is a new selection, then remove any already selected shapes from it */
- if( shapesToSelect ) {
- /* is the new selection a non-empty list of items? */
- if( GXGetShapeType(shapesToSelect) == gxPictureType && (count = GXGetPicture(shapesToSelect, nil, nil, nil, nil)) != 0) {
- /*** bring all the new items to the front in the order that they are in shapesToSelect */
-
- /* make a copy of the new item list to be selected so that we can munge the list */
- shapesToSelect = GXCopyToShape(nil, shapesToSelect);
-
- do { /* remove all the already selected items from our new list to select */
- gxShape item;
-
- /* if the item in our new selection is already selected, then remove it from our new selection */
- GXGetPictureParts(shapesToSelect, count, 1, &item, nil, nil, nil);
- if( targetPtr->selection && ShapeInPicture(item, targetPtr->selection) ||
- ShapeInPicture(item, targetPtr->items) == false )
- GXSetPictureParts(shapesToSelect, count, 1, 0, nil, nil, nil, nil);
- } while( --count );
-
- /* if there are any items left in the new list to be selected, then add them to the current selection */
- count = GXGetPicture(shapesToSelect, nil, nil, nil, nil);
- if (count) {
- do { /* note that we don’t bring these items to the front, since we have already done this */
- gxShape item;
-
- GXGetPictureParts(shapesToSelect, count, 1, &item, nil, nil, nil);
- SelectShape(targetPtr, item, false, false);
- updateControls = true;
- } while( --count );
- }
-
- /* dispose of our munged copy of the new items that have been selected */
- GXDisposeShape(shapesToSelect);
- } else if( ShapeInPicture(shapesToSelect, targetPtr->selection) == false ) {
- if( ShapeInPicture(shapesToSelect, targetPtr->items) ) {
- SelectShape(targetPtr, shapesToSelect, bringToFront, false);
- updateControls = true;
- }
- }
- }
-
- /* allow the selection’s controls to get re-built and re-build them if they have changed */
- --targetPtr->buildHiddenLevel;
- if( updateControls )
- BuildSelectionControls(targetPtr);
-
- HUnlock((Handle)target);
- }
-
-
- gxShape GetShapeControlSelectionHandles(const shapeControl source)
- {
- NilParamReturn(source);
-
- if( (*source)->controls )
- return GXCopyDeepToShape(nil, (*source)->controls);
- else
- return nil;
- }
-
-
- Boolean SendEventToShapeControl(shapeControl target, EventRecord *event)
- {
- Boolean handledEvent = false;
-
- NilParamReturn(target);
- NilParamReturn(event);
-
- HLock((Handle)target);
- switch( event->what ) {
- case keyDown:
- break; /*** change this to handle the key and return true if it is ours */
- case mouseDown:
- { gxPoint originalClick;
- gxHitTestInfo result;
- gxShape itemShape;
- long command;
- shapeControlPtr targetPtr = *target;
-
- { gxViewPort originalPort = *DereferenceViewPortList(targetPtr->originalPorts);
- GXConvertQDPoint(&event->where, originalPort, &originalClick);
- }
-
- /* if there is a selection, then see if any of the selection’s controls have been hit and track them if they have */
- if( targetPtr->selection ) {
- if( GXHitTestPicture(targetPtr->controls, &originalClick, &result, 1, 1) != nil/*gxNoPart*/ ) {
- TrackShapeControl(targetPtr, result.containerIndex, originalClick);
- handledEvent = true;
- break;
- }
- }
-
- /* see if an item gxShape was hit; if so then add it to the selection and track it */
- if( GXHitTestPicture(targetPtr->items, &originalClick, &result, 1, 1) != nil/*gxNoPart*/ ) {
- command = commandMove;
- itemShape = result.which;
-
- if( targetPtr->selection && ShapeInPicture(itemShape, targetPtr->selection) ) {
- if( event->modifiers & shiftKey ) {
- /* the gxShape was already selected and we shift-clicked it, so deselect it and return */
- DeselectShape(targetPtr, itemShape);
- RedrawShapeControl(targetPtr);
- handledEvent = true;
- break;
- }
- } else {
- /* select the new gxShape - the last two parameters are (Boolean replaceSelection, bringToFront) */
- SelectShape(targetPtr, itemShape, (event->modifiers & shiftKey) == 0,
- (event->modifiers & optionKey) != 0);
- RedrawShapeControl(targetPtr);
- }
-
- /* allow the user to move the entire selection around */
- TrackShapeControl(targetPtr, commandMove, originalClick);
- handledEvent = true;
- break;
- }
-
- /* see if we are within the bounds of any of the original viewPorts of the items */
- { gxShape testShape = GXNewPoint(&originalClick);
- gxViewPort *portList = DereferenceViewPortList(targetPtr->originalPorts);
-
- #ifdef debugging
- GXIgnoreGraphicsNotice(transform_viewPorts_already_set);
- #endif
- GXSetShapeViewPorts(testShape, CountViewPortList(targetPtr->originalPorts), portList);
- #ifdef debugging
- GXPopGraphicsNotice();
- #endif
- /* scan through all the original viewPorts of the items */
- while( *portList ) {
- /* if a gxPoint at the original click location would draw to any devices in this port, then we are
- within the bounds of the port. we should now drag out a gray gxRectangle to select all the items
- contained within it */
- if( GXGetShapeGlobalViewDevices(testShape, *portList, nil) ) {
- GXDisposeShape(testShape);
-
- #if 0 /*** needs work */
- TrackShapeControl(targetPtr, commandSelect, originalClick);
- #else
- /* for now, just de-select all the items */
- SelectShape(targetPtr, nil, true, false);
- #endif
-
- RedrawShapeControl(targetPtr);
- ReleaseViewPortList(targetPtr->originalPorts);
- HUnlock((Handle)target);
- return true;
- }
- ++portList;
- }
- GXDisposeShape(testShape);
- ReleaseViewPortList(targetPtr->originalPorts);
- }
-
- /* nothing was hit, so break and return that we didn’t handle the event */
- break;
- }
- }
-
- HUnlock((Handle)target);
- return handledEvent;
- }
-
-
- void InvalidateShapeControlShape(shapeControl target, gxShape invalidShape)
- {
- NilParamReturn(target);
- NilShapeReturn(invalidShape);
-
- HLock((Handle)target);
- InvalidatePicture(*target, invalidShape);
- HUnlock((Handle)target);
- }
-
-
- void InvalidateShapeControlRectangle(shapeControl target, gxRectangle *bounds)
- {
- NilParamReturn(target);
- NilParamReturn(bounds);
-
- HLock((Handle)target);
- InvalidateRectangle(*target, bounds);
- HUnlock((Handle)target);
- }
-
-
- void UpdateShapeControl(shapeControl target)
- {
- NilParamReturn(target);
- HLock((Handle)target);
- RedrawShapeControl(*target);
- HUnlock((Handle)target);
- }
-